/*
 * This file is part of Annuaire.
 *
 * Annuaire is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Annuaire is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Annuaire.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.miage.annuaire;

/**
 * Cette classe représente un membre de l'annuaire. Un membre appartient à une
 * (et une seule) structure. Il est identifié par sa clé.
 * @author guhumber
 */
public class Membre {

	/**
	 * Constructeur vide par défaut.
	 */
	public Membre() {
		// Rien.
	}

	/**
	 * Constructeur qui initialise quelques attributs.
	 * @param key La clef du membre qui permet de l'identifier.
	 * @param name Le nom du membre (il n'y a pas de distinction entre le nom et
	 * le prénom).
	 * @param phone Le numéro de téléphone du membre.
	 * @param office Le bureau du membre.
	 * @param function La fonction exerciée par ce membre.
	 */
	public Membre(String key, String name, String phone, String office,
			String function) {
		this.key = key;
		this.name = name;
		this.phone = phone;
		this.office = office;
		this.function = function;
	}
	
	/**
	 * Renvoie une représentation textuelle de ce membre.
	 * @return Ce membre au format texte.
	 */
	@Override
	public String toString() {
		String structureKey = null;
		if (this.structure != null) {
			structureKey = this.structure.getKey();
		}
		
		return "Personne{" + "key=" + this.key + "; name=" + this.name
				+ "; phone=" + this.phone + "; office=" + this.office
				+ "; function=" + this.function + "; titre=" + this.titre
				+ "; structureKey=" + structureKey + "; leader=" + this.leader
				+ "; contact= " + this.contact + "; assistantLeader= " 
				+ this.assistantLeader + "}";
	}

	/**
	 * Génère un hash grâce aux attributs de ce membre.
	 * @return Un hash de ce membre.
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		
		result = prime * result
				+ ((this.key == null) ? 0 : this.key.hashCode());
		
		result = prime * result
				+ ((this.name == null) ? 0 : this.name.hashCode());
		
		result = prime * result
				+ ((this.phone == null) ? 0 : this.phone.hashCode());
		
		result = prime * result
				+ ((this.office == null) ? 0 : this.office.hashCode());
		
		result = prime * result
				+ ((this.function == null) ? 0 : this.function.hashCode());
		
		result = prime * result
				+ ((this.titre == null) ? 0 : this.titre.hashCode());
		
		result = prime * result + (this.leader ? 1231 : 1237);
		
		result = prime * result + (this.contact ? 1231 : 1237);
		
		result = prime * result + (this.assistantLeader ? 1231 : 1237);

		if (this.structure != null) {
			result = prime * result + ((this.structure.getKey() == null)
					? 0 : this.structure.getKey().hashCode());
			
			result = prime * result + ((this.structure.getShortName() == null)
					? 0 : this.structure.getShortName().hashCode());
			
			result = prime * result + ((this.structure.getCompleteName()
					== null) ? 0 : this.structure.getCompleteName().hashCode());
		}
		
		return result;
	}

	/**
	 * Définit l'égalité entre deux membres.
	 * @param obj L'objet à comparer à ce membre.
	 * @return Vrai si obj est considéré comme égal à ce membre, faux sinon.
	 */
	@Override
	public boolean equals(Object obj) {
		
		if (this == obj) {
			return true;
		}
			
		if (obj == null) {
			return false;
		}
			
		if (!(obj instanceof Membre)) {
			return false;
		}
			
		return this.hashCode() == obj.hashCode();
	}

	/**
	 * Accesseur en lecture sur l'attribut 'key'.
	 * @return La clef du membre qui permet de l'identifier.
	 */
	public String getKey() {
		return this.key;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'key'.
	 * @param key La clef du membre qui permet de l'identifier.
	 */
	public void setKey(String key) {
		this.key = key;
	}
	
	/**
	 * Accesseur en lecture sur l'attribut 'name'.
	 * @return Le nom du membre (il n'y a pas de distinction entre le nom et le
	 * prénom).
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'name'.
	 * @param name Le nom du membre (il n'y a pas de distinction entre le nom et
	 * le prénom).
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'phone'.
	 * @return Le numéro de téléphone du membre.
	 */
	public String getPhone() {
		return this.phone;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'phone'.
	 * @param phone Le numéro de téléphone du membre.
	 */
	public void setPhone(String phone) {
		this.phone = phone;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'office'.
	 * @return Le bureau du membre.
	 */
	public String getOffice() {
		return this.office;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'office'.
	 * @param office Le bureau du membre.
	 */
	public void setOffice(String office) {
		this.office = office;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'function'.
	 * @return La fonction exerciée par ce membre.
	 */
	public String getFunction() {
		return this.function;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'function'.
	 * @param function La fonction exerciée par ce membre.
	 */
	public void setFunction(String function) {
		this.function = function;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'titre'.
	 * @return Le titre que détient ce membre (ex.: chef du département xxx).
	 */
	public String getTitre() {
		return this.titre;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'titre'.
	 * @param titre Le titre que détient ce membre (ex.: chef du département
	 * xxx).
	 */
	public void setTitre(String titre) {
		this.titre = titre;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'structure'.
	 * @return La structure à laquelle appartient ce membre.
	 */
	public Structure getStructure() {
		return this.structure;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'structure'.
	 * @param structure La structure à laquelle appartient ce membre.
	 */
	public void setStructure(Structure structure) {
		
		if (this.structure == null && structure == null) {
			return;
		} else if (this.structure != null && this.structure.equals(structure)) {
			return;
		}
		
		if (structure != null  && structure.getChilds().contains(this)) {
			return;
		}
		
		if (this.structure != null) {
			this.structure.removeMembre(this);
		}
		
		this.structure = structure;
		
		if (this.structure != null) {
			this.structure.addMembre(this);
		}

	}

	/**
	 * Accesseur en lecture sur l'attribut 'leader'.
	 * @return Ce membre est-il leader de sa structure?
	 */
	public boolean isLeader() {
		return this.leader;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'leader'.
	 * @param leader Ce membre est-il leader de sa structure?
	 */
	public void setLeader(boolean leader) {
		
		// Si l'attribut a déjà la bonne valeur, on a rien à faire.
		if (this.leader == leader) {
			return;
		}
		
		// On vire le leader de la structure.	
		if (this.structure != null && this.structure.getLeader() != null
				&& this.structure.getLeader().equals(this) == false) {
			this.structure.getLeader().setLeader(false);
		}
		
		// Mise à jour de l'attribut.
		this.leader = leader;
	}

	/**
	 * Accesseur en lecture sur l'attribut 'contact'.
	 * @return Ce membre est-il le contact de sa structure?
	 */
	public boolean isContact() {
		return this.contact;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'contact'.
	 * @param contact Ce membre est-il le contact de sa structure?
	 */
	public void setContact(boolean contact) {
		
		// Si l'attribut a déjà la bonne valeur, on a rien à faire.
		if (this.contact == contact) {
			return;
		}
		
		// On vire tous le contact de la structure.
		if (this.structure != null && this.structure.getContact() != null
				&& this.structure.getContact().equals(this) == false) {
			this.structure.getContact().setContact(false);
		}
		
		// Mise à jour de l'attribut.
		this.contact = contact;
	}
	
	/**
	 * Accesseur en lecture sur l'attribut 'assistantLeader'.
	 * @return Ce membre est-il assistant au leader de sa structure?
	 */
	public boolean isAssistantLeader() {
		return this.assistantLeader;
	}

	/**
	 * Accesseur en écriture sur l'attribut 'assistantLeader'.
	 * @param assistantLeader Ce membre est-il assistant au leader de sa
	 * structure?
	 */
	public void setAssistantLeader(boolean assistantLeader) {
		this.assistantLeader = assistantLeader;
	}

	/**
	 * La clef du membre qui permet de l'identifier.
	 */
	private String key = null;

	/**
	 * Le nom du membre (il n'y a pas de distinction entre le nom et le prénom).
	 */
	private String name = null;

	/**
	 * Le numéro de téléphone du membre.
	 */
	private String phone = null;

	/**
	 * Le bureau du membre.
	 */
	private String office = null;

	/**
	 * La fonction exerciée par ce membre.
	 */
	private String function = null;

	/**
	 * Le titre que détient ce membre (ex.: chef du département xxx).
	 */
	private String titre = null;
	
	/**
	 * La structure à laquelle appartient ce membre.
	 */
	private Structure structure = null;

	/**
	 * Ce membre est-il leader de sa structure?
	 */
	private boolean leader = false;

	/**
	 * Ce membre est-il le contact de sa structure?
	 */
	private boolean contact = false;
	
	/**
	 * Ce membre est-il assistant au leader de sa structure?
	 */
	private boolean assistantLeader = false;

}
